/*
=======================================================
Carleton, Jillian
Lee, Andrew

CIS 15BG
Professor Singh
due date: 6/15/13
date submitted: 6/15/13
compiled with GCC 32-bit 4.7.2 on Windows 64-bit

Extra Credit part 1

An address book program that has the following data:

* Name (first, middle, last)
* Address
* Phone number

And has the following features:

* Adding a new record; realloc necessary memory.
* Search by last name.
* Update an existing record.
* Delete a record.


Also keep in mind features necessary down the road
for part 2 of this assignment:

* Searching by phone number, any word in the address,
  and either first or last name.

Part 2 implementation requires construction of new
structs that "index the values and memorylocation for
record. Searches should be done on the index structs."
=======================================================
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define FILE_NAME "data.txt"
#define ROW_LENGTH 80
#define NAME_LENGTH 90
#define ADDRESS_LENGTH 90
#define ZIP_LENGTH 10
#define PHONE_LENGTH 12


typedef struct {
	char *first;
	char *middle;
	char *last;
} name_t;

typedef struct {
	char *number;
	char *street;
	char *street2;
	char *city;
	char *state;
	char *zip;
} address_t;

typedef struct {
	name_t name;
	address_t *address;
	char *phone;
	int addressCount;
	int phoneCount;
} contact_t;


void ReadData( contact_t **contacts, int *count );
int SearchContact (contact_t **contacts, int *count);
void UpdateContact( contact_t **contacts, int count );
void DeleteContact( contact_t **contacts, int i, int *count );
void AllocateMemoryForContact( contact_t **contacts, int count );
void AllocateMemoryForName( name_t *name );
void AllocateMemoryForAddress( address_t **address, int addressCount );
void AllocateMemoryForPhone( char **phone, int phoneCount );
void DrawMenu( int count, int maxChoice );
void DrawUpdateMenu( int maxChoice );
int DrawPrompt( int maxChoice );
void DrawContact( contact_t *contacts, int i, int j );


int main( void ) {
	contact_t *contacts = NULL;
	address_t *ptr = NULL;
	char *target = NULL;
	int count = 0, menuChoice, updateChoice, menuChoices = 4, updateChoices = 3, i, loc;
	char answer;

	// create database from file
	ReadData( &contacts, &count );

	do {
		DrawMenu( count, menuChoices );
		menuChoice = DrawPrompt( menuChoices );

		switch ( menuChoice ) {
			case 1:	DrawContact( contacts, 0, count );
					break;
			// add contact using console input
			case 2: AllocateMemoryForContact( &contacts, count );
					UpdateContact( &contacts, count );
					DrawContact( contacts, count, count + 1 );
					count++;
					break;
			case 3: loc = SearchContact(&contacts, &count);
					if ( loc != -1 ) {
						DrawContact( contacts, loc, loc + 1 );

						DrawUpdateMenu( updateChoices );
						updateChoice = DrawPrompt( updateChoices );
						switch ( updateChoice ) {
							case 1: UpdateContact( &contacts, loc );
									DrawContact( contacts, loc, loc + 1 );
									break;
							case 2: DeleteContact( &contacts, loc, &count );
									printf( "\nContact deleted.\n" );
									break;
						}
					}
					break;
		}
	} while ( menuChoice != menuChoices );

	// quitting program
	for ( i = count - 1; i >= 0; i-- ) {
		free( ( contacts + i )->phone );
		free( ( contacts + i )->address->zip );
		free( ( contacts + i )->address->state );
		free( ( contacts + i )->address->city );
		free( ( contacts + i )->address->street2 );
		free( ( contacts + i )->address->street );
		free( ( contacts + i )->address->number );
		if ( ( contacts + i )->addressCount == 1 ) {
			ptr = ( contacts + i )->address;
			free( ( ptr + 1 )->zip );
			free( ( ptr + 1 )->state );
			free( ( ptr + 1 )->city );
			free( ( ptr + 1 )->street2 );
			free( ( ptr + 1 )->street );
			free( ( ptr + 1 )->number );
		}
		free( ( contacts + i )->name.last );
		free( ( contacts + i )->name.middle );
		free( ( contacts + i )->name.first );
		free( ( contacts + i )->address );
	}

	free( contacts );

	return 0;
}


void ReadData( contact_t **contacts, int *count ) {
	FILE *file;
	char *temp, *newline;
	address_t *ptr = NULL;

	file = fopen( FILE_NAME, "r" );
	if ( file == NULL ) {
		printf( "\nERROR: Can't open %s\n", FILE_NAME );
		exit( EXIT_FAILURE );
	}

	// temp will be used to store a row at a time, the default size
	// being 80 columns.
	temp = calloc( ROW_LENGTH + 1, sizeof( char ) );
	if ( temp == NULL ) {
		printf( "\nOut of memory\n" );
		exit( EXIT_FAILURE );
	}

	// read in what should be the first row of eighteen rows from the file
	// and is the start of an individual contact's info (their first name).
	// If it fails to read in a line or reads only a newline char, we've
	// reached the end of our contact list.
	while ( ( fgets( temp, ROW_LENGTH + 1, file ) != NULL ) && ( strcmp( temp, "\n" ) != 0 ) ) {
		// if we're inside here, we will read in seventeen more rows
		// (the rest of a person's info), before returning to this
		// while loop to check for an additional person.

		AllocateMemoryForContact( contacts, *count );

		if ( ( newline = strchr( temp, '\n' ) ) != NULL ) {
			*newline = '\0';
		}
		strcpy( ( *contacts + *count )->name.first, temp );

		// middle name
		fgets( temp, ROW_LENGTH + 1, file );
		if ( ( newline = strchr( temp, '\n' ) ) != NULL ) {
			*newline = '\0';
		}
		strcpy( ( *contacts + *count )->name.middle, temp );

		// last name
		fgets( temp, ROW_LENGTH + 1, file );
		if ( ( newline = strchr( temp, '\n' ) ) != NULL ) {
			*newline = '\0';
		}
		strcpy( ( *contacts + *count )->name.last, temp );

		// street number
		fgets( temp, ROW_LENGTH + 1, file );
		if ( ( newline = strchr( temp, '\n' ) ) != NULL ) {
			*newline = '\0';
		}
		strcpy( ( *contacts + *count )->address->number, temp );

		// street name
		fgets( temp, ROW_LENGTH + 1, file );
		if ( ( newline = strchr( temp, '\n' ) ) != NULL ) {
			*newline = '\0';
		}
		strcpy( ( *contacts + *count )->address->street, temp );

		// street name 2
		fgets( temp, ROW_LENGTH + 1, file );
		if ( ( newline = strchr( temp, '\n' ) ) != NULL ) {
			*newline = '\0';
		}
		strcpy( ( *contacts + *count )->address->street2, temp );

		// city
		fgets( temp, ROW_LENGTH + 1, file );
		if ( ( newline = strchr( temp, '\n' ) ) != NULL ) {
			*newline = '\0';
		}
		strcpy( ( *contacts + *count )->address->city, temp );

		// state
		fgets( temp, ROW_LENGTH + 1, file );
		if ( ( newline = strchr( temp, '\n' ) ) != NULL ) {
			*newline = '\0';
		}
		strcpy( ( *contacts + *count )->address->state, temp );

		// zip
		fgets( temp, ROW_LENGTH + 1, file );
		if ( ( newline = strchr( temp, '\n' ) ) != NULL ) {
			*newline = '\0';
		}
		strcpy( ( *contacts + *count )->address->zip, temp );

		// check if 2nd address is present, allocate memory if so
		fgets( temp, ROW_LENGTH + 1, file );
		if ( strcmp( temp, "\n" ) != 0 ) {
			( *contacts + *count )->addressCount++;
			AllocateMemoryForAddress( &( ( *contacts + *count )->address ), ( *contacts + *count )->addressCount );
			if ( ( newline = strchr( temp, '\n' ) ) != NULL ) {
				*newline = '\0';
			}
			ptr = ( *contacts + *count )->address;
			strcpy( ( ptr + 1 )->number, temp );

			// 2nd address street name
			fgets( temp, ROW_LENGTH + 1, file );
			if ( ( newline = strchr( temp, '\n' ) ) != NULL ) {
				*newline = '\0';
			}
			strcpy( ( ptr + 1 )->street, temp );

			// 2nd address street name 2
			fgets( temp, ROW_LENGTH + 1, file );
			if ( ( newline = strchr( temp, '\n' ) ) != NULL ) {
				*newline = '\0';
			}
			strcpy( ( ptr + 1 )->street2, temp );

			// 2nd address city
			fgets( temp, ROW_LENGTH + 1, file );
			if ( ( newline = strchr( temp, '\n' ) ) != NULL ) {
				*newline = '\0';
			}
			strcpy( ( ptr + 1 )->city, temp );

			// 2nd address state
			fgets( temp, ROW_LENGTH + 1, file );
			if ( ( newline = strchr( temp, '\n' ) ) != NULL ) {
				*newline = '\0';
			}
			strcpy( ( ptr + 1 )->state, temp );

			// 2nd address zip
			fgets( temp, ROW_LENGTH + 1, file );
			if ( ( newline = strchr( temp, '\n' ) ) != NULL ) {
				*newline = '\0';
			}
			strcpy( ( ptr + 1 )->zip, temp );
		} else {
			fgets( temp, ROW_LENGTH + 1, file );
			fgets( temp, ROW_LENGTH + 1, file );
			fgets( temp, ROW_LENGTH + 1, file );
			fgets( temp, ROW_LENGTH + 1, file );
			fgets( temp, ROW_LENGTH + 1, file );
		}

		// phone number
		fgets( temp, ROW_LENGTH + 1, file );
		if ( ( newline = strchr( temp, '\n' ) ) != NULL ) {
			*newline = '\0';
		}
		strcpy( ( *contacts + *count )->phone, temp );

		// check if 2nd phone number exists, allocate memory if so
		fgets( temp, ROW_LENGTH + 1, file );
		if ( strcmp( temp, "\n" ) != 0 ) {
			( *contacts + *count )->phoneCount++;
			AllocateMemoryForPhone( &( ( *contacts + *count )->phone ), ( *contacts + *count )->phoneCount );

			if ( ( newline = strchr( temp, '\n' ) ) != NULL ) {
				*newline = '\0';
			}
			strncat( ( *contacts + *count )->phone, temp, PHONE_LENGTH );
		}

		// check if 3rd phone number exists
		if ( ( fgets( temp, ROW_LENGTH + 1, file ) != NULL ) && ( strcmp( temp, "\n" ) != 0 ) ) {
			( *contacts + *count )->phoneCount++;
			AllocateMemoryForPhone( &( ( *contacts + *count )->phone ), ( *contacts + *count )->phoneCount );

			if ( ( newline = strchr( temp, '\n' ) ) != NULL ) {
				*newline = '\0';
			}
			strncat( ( *contacts + *count )->phone, temp, PHONE_LENGTH );
		}

		( *count )++;
	}


	fclose( file );
}


void AllocateMemoryForContact( contact_t **contacts, int count ) {
	*contacts = realloc( *contacts, ( count + 1 ) * sizeof( contact_t ) );
	if ( *contacts == NULL ) {
		printf( "\nOut of memory\n" );
		exit( EXIT_FAILURE );
	}

	AllocateMemoryForName( &( ( *contacts + count )->name) );
	AllocateMemoryForAddress( &( ( *contacts + count )->address ), 0 );
	AllocateMemoryForPhone( &( ( *contacts + count )->phone ), 0 );
	( *contacts + count )->addressCount = 0;
	( *contacts + count )->phoneCount = 0;
}


void AllocateMemoryForName( name_t *name ) {
	name->first = calloc( NAME_LENGTH + 1, sizeof( char ) );
	if ( name->first == NULL ) {
		printf( "\nOut of memory\n" );
		exit( EXIT_FAILURE );
	}

	name->middle = calloc( NAME_LENGTH + 1, sizeof( char ) );
	if ( name->middle == NULL ) {
		printf( "\nOut of memory\n" );
		exit( EXIT_FAILURE );
	}

	name->last = calloc( NAME_LENGTH + 1, sizeof( char ) );
	if ( name->last == NULL ) {
		printf( "\nOut of memory\n" );
		exit( EXIT_FAILURE );
	}
}


void AllocateMemoryForAddress( address_t **address, int addressCount ) {
	if ( addressCount == 0 ) {
		*address = calloc( 1, sizeof ( address_t ) );
	} else {
		*address = realloc( *address, ( addressCount + 1 ) * sizeof ( address_t ) );
	}
	if ( *address == NULL ) {
		printf( "\nOut of memory\n" );
		exit( EXIT_FAILURE );
	}

	( *address + addressCount )->number = calloc( ADDRESS_LENGTH + 1, sizeof( char ) );
	if ( ( *address + addressCount )->number == NULL ) {
		printf( "\nOut of memory\n" );
		exit( EXIT_FAILURE );
	}

	( *address + addressCount )->street = calloc( ADDRESS_LENGTH + 1, sizeof( char ) );
	if ( ( *address + addressCount )->street == NULL ) {
		printf( "\nOut of memory\n" );
		exit( EXIT_FAILURE );
	}

	( *address + addressCount )->street2 = calloc( ADDRESS_LENGTH + 1, sizeof( char ) );
	if ( ( *address + addressCount )->street2 == NULL ) {
		printf( "\nOut of memory\n" );
		exit( EXIT_FAILURE );
	}

	( *address + addressCount )->city = calloc( ADDRESS_LENGTH + 1, sizeof( char ) );
	if ( ( *address + addressCount )->city == NULL ) {
		printf( "\nOut of memory\n" );
		exit( EXIT_FAILURE );
	}

	( *address + addressCount )->state = calloc( ADDRESS_LENGTH + 1, sizeof( char ) );
	if ( ( *address + addressCount )->state == NULL ) {
		printf( "\nOut of memory\n" );
		exit( EXIT_FAILURE );
	}

	( *address + addressCount )->zip = calloc( ZIP_LENGTH + 1, sizeof( char ) );
	if ( ( *address + addressCount )->zip == NULL ) {
		printf( "\nOut of memory\n" );
		exit( EXIT_FAILURE );
	}

}


void AllocateMemoryForPhone( char **phone, int phoneCount ) {
	if ( phoneCount == 0 ) {
		*phone = calloc( PHONE_LENGTH + 1, sizeof( char ) );
	} else {
		*phone = realloc( *phone, ( ( phoneCount + 1 ) * PHONE_LENGTH + 1 ) * sizeof( char ) );
	}

	if ( *phone == NULL ) {
		printf( "\nOut of memory\n" );
		exit( EXIT_FAILURE );
	}
}


int SearchContact ( contact_t **contacts, int *count )
{
    int i, found = -1;
    char *target = NULL;

    target = realloc(target, NAME_LENGTH * sizeof( char ));

    printf("\nPlease enter the last name you would like to search for: ");
    scanf("%s", target);

    for(i = 0; i < *count; i++) {
	    if ( strcmp( target, ( *contacts + i )->name.last ) == 0 )
	    {
        	found = i;
        	break;
    	}
	}

	if ( found == -1 ) {
        printf( "\nSorry, last name not found.\n" );
	}

	return found;
}


/*
=========================================================
UpdateContact

	Prompts user for all fields and saves input.
	This function is used both when selecting Add Contact
	from the main menu, as well as the Update Contact
	in the search menu, to overwrite contact info for an
	existing contact.
=========================================================
*/
void UpdateContact( contact_t **contacts, int count ) {
	char *temp, *newline;
	char reply = ' ';
	address_t *ptr = ( *contacts + count )->address;

	temp = calloc( ROW_LENGTH + 1, sizeof( char ) );
	if ( temp == NULL ) {
		printf( "\nOut of memory\n" );
		exit( EXIT_FAILURE );
	}

	// Reset current contact by first deleting any
	// existing 2nd addresses and additional phone numbers.
	if ( ( *contacts + count )->addressCount == 1 ) {
		free( ( ptr + 1 )->zip );
		free( ( ptr + 1 )->state );
		free( ( ptr + 1 )->city );
		free( ( ptr + 1 )->street2 );
		free( ( ptr + 1 )->street );
		free( ( ptr + 1 )->number );

		( *contacts + count )->address = realloc( ( *contacts + count )->address, sizeof ( address_t ) );
		if ( ( *contacts + count )->address == NULL ) {
			printf( "\nOut of memory\n" );
			exit( EXIT_FAILURE );
		}

		( *contacts + count )->addressCount--;
	}

	if ( ( *contacts + count )->phoneCount > 0 ) {
		( *contacts + count )->phone = realloc( ( *contacts + count )->phone, ( PHONE_LENGTH + 1 ) * sizeof( char ) );
		if ( ( *contacts + count )->phone == NULL ) {
			printf( "\nOut of memory\n" );
			exit( EXIT_FAILURE );
		}

		( *contacts + count )->phoneCount = 0;
	}

    fflush( stdin );
    printf( "\nPlease enter the first name: " );
    fgets( ( *contacts + count )->name.first, ROW_LENGTH + 1, stdin );
    if ( ( newline = strchr( ( *contacts + count )->name.first, '\n' ) ) != NULL )
    	*newline = '\0';
    fflush( stdin );

    printf( "Please enter the middle name: " );
    fgets ( ( *contacts + count )->name.middle, ROW_LENGTH + 1, stdin );
    if ( ( newline = strchr( ( *contacts + count )->name.middle, '\n' ) ) != NULL )
    	*newline = '\0';
    fflush( stdin );

    printf("Please enter the last name: ");
    fgets ( ( *contacts + count )->name.last, ROW_LENGTH + 1, stdin );
    if ( ( newline = strchr( ( *contacts + count )->name.last, '\n' ) ) != NULL )
    	*newline = '\0';
    fflush( stdin );

    printf( "Please enter the street number: " );
    fgets ( ( *contacts + count )->address->number, ROW_LENGTH + 1, stdin );
    if ( ( newline = strchr( ( *contacts + count )->address->number, '\n' ) ) != NULL )
    	*newline = '\0';
    fflush( stdin );

    printf( "Please enter the street name: " );
    fgets ( ( *contacts + count )->address->street, ROW_LENGTH + 1, stdin );
    if ( ( newline = strchr( ( *contacts + count )->address->street, '\n' ) ) != NULL )
    	*newline = '\0';
    fflush( stdin );

    printf( "Please enter any additional part of the address: " );
    fgets ( ( *contacts + count )->address->street2, ROW_LENGTH + 1, stdin );
    if ( ( newline = strchr( ( *contacts + count )->address->street2, '\n' ) ) != NULL )
    	*newline = '\0';
    fflush( stdin );

    printf( "Please enter the city: " );
    fgets( ( *contacts + count )->address->city, ROW_LENGTH + 1, stdin );
    if ( ( newline = strchr( ( *contacts + count )->address->city, '\n' ) ) != NULL )
    	*newline = '\0';
    fflush( stdin );

    printf( "Please enter the state: " );
    fgets( ( *contacts + count )->address->state, ROW_LENGTH + 1, stdin );
    if ( ( newline = strchr( ( *contacts + count )->address->state, '\n' ) ) != NULL )
    	*newline = '\0';
    fflush( stdin );

    printf( "Please enter the zip: " );
    fgets( ( *contacts + count )->address->zip, ROW_LENGTH + 1, stdin );
    if ( ( newline = strchr( ( *contacts + count )->address->zip, '\n' ) ) != NULL )
    	*newline = '\0';
    fflush( stdin );

	do {
		fflush( stdin );
		printf( "Would you like to enter a second address? (Y/N): ");
	} while ( ( scanf( "%c", &reply ) != 1 ) || !( ( reply == 'Y' ) || ( reply == 'y' )
											   || ( reply == 'N' ) || ( reply == 'n' ) ) );

	fflush( stdin );
    if ( ( reply == 'Y' ) || ( reply == 'y' ) ) {
    	( *contacts + count )->addressCount++;
        AllocateMemoryForAddress( &( ( *contacts + count )->address ), ( *contacts + count )->addressCount );
        ptr = ( *contacts + count )->address;

	    printf( "Please enter the street number: " );
    	fgets ( ( ptr + 1 )->number, ROW_LENGTH + 1, stdin );
    	if ( ( newline = strchr( ( ptr + 1 )->number, '\n' ) ) != NULL )
    	*newline = '\0';
    	fflush( stdin );

    	printf( "Please enter the street name: " );
    	fgets ( ( ptr + 1 )->street, ROW_LENGTH + 1, stdin );
    	if ( ( newline = strchr( ( ptr + 1 )->street, '\n' ) ) != NULL )
    	*newline = '\0';
    	fflush( stdin );

    	printf( "Please enter any additional part of the address: " );
    	fgets ( ( ptr + 1 )->street2, ROW_LENGTH + 1, stdin );
    	if ( ( newline = strchr( ( ptr + 1 )->street2, '\n' ) ) != NULL )
	    	*newline = '\0';
	    fflush( stdin );

    	printf( "Please enter the city: " );
    	fgets( ( ptr + 1 )->city, ROW_LENGTH + 1, stdin );
    	if ( ( newline = strchr( ( ptr + 1 )->city, '\n' ) ) != NULL )
	    	*newline = '\0';
	    fflush( stdin );

    	printf( "Please enter the state: " );
    	fgets( ( ptr + 1 )->state, ROW_LENGTH + 1, stdin );
    	if ( ( newline = strchr( ( ptr + 1 )->state, '\n' ) ) != NULL )
	    	*newline = '\0';
	    fflush( stdin );

    	printf( "Please enter the zip: " );
    	fgets( ( ptr + 1 )->zip, ROW_LENGTH + 1, stdin );
    	if ( ( newline = strchr( ( ptr + 1 )->zip, '\n' ) ) != NULL )
	    	*newline = '\0';
	    fflush( stdin );
    }

    //phone number
    fflush( stdin );
    printf( "\nPlease enter the phone number (XXX-XXX-XXXX): " );
	fgets( temp, PHONE_LENGTH + 1, stdin );
	if ( ( newline = strchr( temp, '\n' ) ) != NULL ) {
		*newline = '\0';
	}
    strcpy( ( *contacts + count )->phone, temp );
    fflush( stdin );

    reply = ' ';
	do {
		fflush( stdin );
		printf( "Would you like to enter an additional phone number? (Y/N): ");
	} while ( ( scanf( "%c", &reply ) != 1 ) || !( ( reply == 'Y' ) || ( reply == 'y' )
											   || ( reply == 'N' ) || ( reply == 'n' ) ) );

	fflush( stdin );
    if ( ( reply == 'Y' ) || ( reply == 'y' ) ) {
        ( *contacts + count )->phoneCount++;
        AllocateMemoryForPhone( &( ( *contacts + count )->phone ), ( *contacts + count )->phoneCount );

        printf( "Please enter the phone number (XXX-XXX-XXXX): " );
		fgets( temp, PHONE_LENGTH + 1, stdin );
		if ( ( newline = strchr( temp, '\n' ) ) != NULL ) {
				*newline = '\0';
		}
		strncat( ( *contacts + count )->phone, temp, PHONE_LENGTH );

		reply = ' ';
		do {
			fflush( stdin );
			printf( "Would you like to enter a third phone number? (Y/N): ");
		} while ( ( scanf( "%c", &reply ) != 1 ) || !( ( reply == 'Y' ) || ( reply == 'y' )
												   || ( reply == 'N' ) || ( reply == 'n' ) ) );
	
		fflush( stdin );
		if ( ( reply == 'Y' ) || ( reply == 'y' ) ) {
	        ( *contacts + count )->phoneCount++;
	        AllocateMemoryForPhone( &( ( *contacts + count )->phone ), ( *contacts + count )->phoneCount );

           	printf( "Please enter the phone number (XXX-XXX-XXXX): " );
			fgets( temp, PHONE_LENGTH + 1, stdin );
			if ( ( newline = strchr( temp, '\n' ) ) != NULL ) {
				*newline = '\0';
			}
			strncat( ( *contacts + count )->phone, temp, PHONE_LENGTH );
    	}	
	}
}


/*
=========================================================
DeleteContact

	First checks to see if the contact to be deleted is
	the last entry. If so, no copying data is necessary;
	simply free the memory for that contact and realloc
	contacts accordingly. If there is only 1 entry to 
	begin with, then set contacts to NULL.

	If the contact to be deleted is NOT the last entry,
	then first reset that entry by getting rid of any
	existing 2nd addresses and 2nd/3rd phone numbers.
	Then copy the last entry (the tail) to overwrite
	all of the info in the contact to be deleted, and
	then shrink contacts by one.
=========================================================
*/
void DeleteContact( contact_t **contacts, int i, int *count ) {
	address_t *ptr = ( *contacts + i )->address, *ptr2 = ( *contacts + ( *count - 1 ) )->address;
	contact_t *del = ( *contacts + i );
	contact_t *tail = ( *contacts + ( *count - 1 ) );

	// Checks to see if the contact to be deleted is the last one.
	// If so, no copying is necessary; simply free that entry
	// and shrink the database by 1.
	if ( i + 1 == *count ) {
		free( ( *contacts + i )->phone );
		free( ( *contacts + i )->address->zip );
		free( ( *contacts + i )->address->state );
		free( ( *contacts + i )->address->city );
		free( ( *contacts + i )->address->street2 );
		free( ( *contacts + i )->address->street );
		free( ( *contacts + i )->address->number );
		if ( ( *contacts + i )->addressCount == 1 ) {	
			free( ( ptr + 1 )->zip );
			free( ( ptr + 1 )->state );
			free( ( ptr + 1 )->city );
			free( ( ptr + 1 )->street2 );
			free( ( ptr + 1 )->street );
			free( ( ptr + 1 )->number );
		}
		free( ( *contacts + i )->name.last );
		free( ( *contacts + i )->name.middle );
		free( ( *contacts + i )->name.first );
		free( ( *contacts + i )->address );
		ptr = NULL;
		if ( i == 0 ) {
			free( *contacts );
			*contacts = NULL;
		} else {
			*contacts = realloc( *contacts, ( *count - 1 ) * sizeof( contact_t ) );
			if ( *contacts == NULL ) {
				printf( "\nOut of memory\n" );
				exit( EXIT_FAILURE );
			}
		}
		// Entry to be deleted is not the last, so we'll reset
		// that node, copy over the last node to overwrite the information,
		// and then shrink the database by 1.
	} else {
		if ( del->addressCount == 1 ) {
			free( ( ptr + 1 )->zip );
			free( ( ptr + 1 )->state );
			free( ( ptr + 1 )->city );
			free( ( ptr + 1 )->street2 );
			free( ( ptr + 1 )->street );
			free( ( ptr + 1 )->number );

			del->address = realloc( del->address, sizeof ( address_t ) );
			if ( del->address == NULL ) {
				printf( "\nOut of memory\n" );
				exit( EXIT_FAILURE );
			}

			del->addressCount--;
		}

		if ( del->phoneCount > 0 ) {
			del->phone = realloc( del->phone, ( PHONE_LENGTH + 1 ) * sizeof( char ) );
			if ( del->phone == NULL ) {
				printf( "\nOut of memory\n" );
				exit( EXIT_FAILURE );
			}

			del->phoneCount = 0;
		}

		strcpy( del->name.first, tail->name.first );
		strcpy( del->name.middle, tail->name.middle );
		strcpy( del->name.last, tail->name.last );
		strcpy( del->address->number, tail->address->number );
		strcpy( del->address->street, tail->address->street );
		strcpy( del->address->street2, tail->address->street2 );
		strcpy( del->address->city, tail->address->city );
		strcpy( del->address->state, tail->address->state );
		strcpy( del->address->zip, tail->address->zip );
		if ( tail->addressCount == 1 ) {
			del->addressCount++;
			AllocateMemoryForAddress( &( del->address ), del->addressCount );
			ptr = ( *contacts + i )->address;
			strcpy( ( ptr + 1 )->number, ( ptr2 + 1 )->number );
			strcpy( ( ptr + 1 )->street, ( ptr2 + 1 )->street );
			strcpy( ( ptr + 1 )->street2, ( ptr2 + 1 )->street2 );
			strcpy( ( ptr + 1 )->city, ( ptr2 + 1 )->city );
			strcpy( ( ptr + 1 )->state, ( ptr2 + 1 )->state );
			strcpy( ( ptr + 1 )->zip, ( ptr2 + 1 )->zip );
		}
		if ( tail->phoneCount > 0 ) {
			AllocateMemoryForPhone( &( del->phone ), tail->phoneCount );
			strcpy( del->phone, tail->phone );
			del->phoneCount = tail->phoneCount; 
		}

		free( tail->phone );
		free( tail->address->zip );
		free( tail->address->state );
		free( tail->address->city );
		free( tail->address->street2 );
		free( tail->address->street );
		free( tail->address->number );
		if ( tail->addressCount == 1 ) {	
			free( ( ptr2 + 1 )->zip );
			free( ( ptr2 + 1 )->state );
			free( ( ptr2 + 1 )->city );
			free( ( ptr2 + 1 )->street2 );
			free( ( ptr2 + 1 )->street );
			free( ( ptr2 + 1 )->number );
		}
		free( tail->name.last );
		free( tail->name.middle );
		free( tail->name.first );
		free( tail->address );
		ptr2 = NULL;

		*contacts = realloc( *contacts, ( *count - 1 ) * sizeof( contact_t ) );
		if ( *contacts == NULL ) {
			printf( "\nOut of memory\n" );
			exit( EXIT_FAILURE );
		}
	}

	( *count )--;
}


void DrawMenu( int count, int maxChoice ) {
	printf( "\n" );
	printf( "=========================================\n" );
	printf( "|\t\tAddress Book\t\t|\n" );
	if ( count == 1 ) {
	printf( "|\t\t1 contact \t\t|\n" );
	} else {
	printf( "|\t\t%d contacts\t\t|\n", count );
	}
	printf( "|\t---------------------------\t|\n" );
	printf( "|\t\t\t\t\t|\n" );
	printf( "|\t%d. Display all contacts\t\t|\n", maxChoice - 3 );
	printf( "|\t%d. Add new contact\t\t|\n", maxChoice - 2 );
	printf( "|\t%d. Search by last name\t\t|\n", maxChoice - 1 );
	printf( "|\t%d. Quit\t\t\t\t|\n", maxChoice );
    printf( "=========================================\n\n" );

}


void DrawUpdateMenu( int maxChoice ) {
	printf( "\n" );
	printf( "=========================================\n" );
	printf( "|\t%d. Update contact\t\t|\n", maxChoice - 2 );
	printf( "|\t%d. Delete contact\t\t|\n", maxChoice - 1 );
	printf( "|\t%d. Return to main menu\t\t|\n", maxChoice );
	printf( "=========================================\n\n" );
}


int DrawPrompt( int maxChoice ) {
	int menuChoice = 0;
	do {
		fflush(stdin);
		printf( "Enter command [1-%d]: ", maxChoice );
	} while ( ( scanf( "%d", &menuChoice ) != 1 ) || !( ( menuChoice >= 1 ) && ( menuChoice <= maxChoice ) ) );

	return menuChoice;
}


/*
=========================================================
DrawContact

	Has all printing format to print one contact to the
	screen. The 2nd argument indicates which contact to
	begin printing, and the 3rd argument is when to stop.

	Example: If you want to print just the 5th contact,
	then call ( 4, 5 ). If you want to print from the 2nd
	to the 10th contact, call with arguments ( 1, 10 ).
=========================================================
*/
void DrawContact( contact_t *contacts, int i, int j ) {
	int a, b;
	address_t *ptr = NULL;
	char *x;
	for ( ; i < j; i++ ) {
		printf( "\n__________________________________" );
		printf( "\n\n%s ", ( contacts + i )->name.first );
		if ( strcmp( ( contacts + i )->name.middle, "" ) != 0 )
			printf( "%s ", ( contacts + i )->name.middle );
		printf( "%s\n", ( contacts + i )->name.last );

		printf( "%s %s\n", ( contacts + i )->address->number, ( contacts + i )->address->street );
		if ( strcmp( ( contacts + i )->address->street2, "" ) != 0 )
			printf( "%s\n", ( contacts + i )->address->street2 );

		printf( "%s, %s %s\n", ( contacts + i )->address->city, ( contacts + i )->address->state, ( contacts + i )->address->zip );

		if ( ( contacts + i )->addressCount == 1 ) {
			ptr = ( contacts + i )->address;
			printf( "\n%s %s\n", ( ptr + 1 )->number, ( ptr + 1 )->street );
			if ( strcmp( ( ptr + 1 )->street2, "" ) != 0 )
				printf( "%s\n", ( ptr + 1 )->street2 );
			printf( "%s, %s %s\n", ( ptr + 1 )->city, ( ptr + 1 )->state, ( ptr + 1 )->zip );
		}

		x = ( contacts + i )->phone;
		for ( a = 0; a <= ( contacts + i )->phoneCount; a++ ) {
			printf( "\n" );
			for ( b = 0; b < PHONE_LENGTH; b++ ) {
				putchar( *x );
				x++;
			}
		}
		printf( "\n__________________________________" );
		printf( "\n\n" );
	}
}